/**
 * kl yy-ds @2021
 */
package com.cxps.server.product.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cxps.cloud.enums.ChannelEnum;
import com.cxps.cloud.enums.DataStatus;
import com.cxps.cloud.enums.SaleTypeEnum;
import com.cxps.cloud.utils.ExportUtils;
import com.cxps.cloud.utils.IdUtils;
import com.cxps.cloud.utils.StringConvertUtil;
import com.cxps.cloud.utils.UploadAndDownloadUtils;
import com.cxps.server.product.domain.ProductEntity;
import com.cxps.server.product.domain.ProductForm;
import com.cxps.server.product.domain.ProductQuery;
import com.cxps.server.product.mapper.ProductMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * 商品服务层
 *
 * @author YouCai.Liu
 * @since 2021/10/18
 * ...
 */
@Slf4j
@Service
public class ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    // 导出模板的位置
    @Value("${cxps.yyds.export-template}")
    private String fileTemplate;

    // 导出的位置
    @Value("${cxps.yyds.export-location}")
    private String exportLocation;

    // 导入的模板位置
    @Value("${cxps.yyds.import-template}")
    private String importFile;

    /**
     * 查询商品列表
     *
     * @param query
     */
    public Page<ProductEntity> productList(ProductQuery query) {

        // 创建 MP 分页对象
        Page<ProductEntity> page = new Page<>(query.getCurrent(), query.getSize());

        // 设置排序字段
        if (StringUtils.isBlank(query.getSortOrder())) {
            // 按照 update_time 倒序排，如果一样在按照 id 正序排
            page.addOrder(OrderItem.desc("update_time")).addOrder(OrderItem.asc("id"));
        } else {
            String sortOrder = query.getSortOrder();
            if (sortOrder.equals("ascending")) {
                page.addOrder(OrderItem.asc(StringConvertUtil.humpConversionUnderscore(query.getSortBy())));
            } else {
                page.addOrder(OrderItem.desc(StringConvertUtil.humpConversionUnderscore(query.getSortBy())));
            }
        }

        // 执行查询
        List<ProductEntity> entityList = productMapper.selectPageList(page, query);
        page.setRecords(entityList);
        return page;
    }

    /**
     * 商品添加
     *
     * @param form
     */
    public void addProduct(ProductForm form) {
        ProductEntity entity = new ProductEntity();
        BeanUtils.copyProperties(form, entity);
        entity.preInsert();
        entity.setId(UUID.randomUUID().toString().replace("-", ""));
        productMapper.insert(entity);
    }

    /**
     * 根据ID查询商品信息
     *
     * @param id
     * @return
     */
    public ProductEntity getProductById(String id) {
        ProductEntity entity = productMapper.selectById(id);
        if (null == entity) {
            return null;
        }
        return entity;
    }

    /**
     * 商品修改
     *
     * @param form
     */
    public void updateProduct(ProductForm form) {
        ProductEntity entity = new ProductEntity();
        BeanUtils.copyProperties(form, entity);
        entity.preUpdate();
        productMapper.updateById(entity);
    }

    /**
     * 商品删除
     *
     * @param ids
     */
    public void delProduct(String[] ids) {
        for (String id : ids) {
            ProductEntity entity = new ProductEntity();
            entity.setId(id);
            entity.setStatus(DataStatus.OFF_LINE.getCode());
            entity.preUpdate();
            productMapper.updateById(entity);
        }
    }

    /**
     * 导出商品
     *
     * @param query
     */
    public void exportData(ProductQuery query) {
        // 限制结果集最大数
        query.setCurrent(1);
        query.setSize(500);
        // 调用查询列表的方法
        Page<ProductEntity> page = productList(query);
        // 获取要导出的数据
        List<ProductEntity> entityList = page.getRecords();
        if (null == entityList || entityList.isEmpty()) {
            return;
        }

        // 导出的文件名
        String fileName = "product-" + System.currentTimeMillis() + ".xlsx";

        ExportUtils<ProductEntity> exportFile = new ExportUtils<>();

        // 1.生成要导出的文件 excel
        exportFile.buildFile(entityList, fileTemplate, exportLocation, fileName);

        // 2.进行响应下载
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        exportFile.exportData(response, exportLocation, fileName);
    }

    /**
     * 导入数据：解析文件，获取数据
     *
     * @param files
     */
    public Map<String, Integer> importData(MultipartFile[] files) throws IOException {
        Map<String, Integer> map = new HashMap<>();
        // 错误数据集合
        List<XSSFRow> errorRows = new ArrayList<>();
        // 成功的数据量
        Integer successCount = 0;
        // 遍历上传的文件集合
        for (MultipartFile file : files) {
            // 创建一个excel工作簿
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());

            // 获取sheet数量
            int numberOfSheets = workbook.getNumberOfSheets();
            for (int i = 0; i < numberOfSheets; i++) {
                // 遍历获取sheet
                XSSFSheet sheet = workbook.getSheetAt(i);

                // 获取sheet里内容开始行和结束行
                int firstRowNum = sheet.getFirstRowNum() + 2;
                int lastRowNum = sheet.getLastRowNum();

                for (int j = firstRowNum; j <= lastRowNum; j++) {
                    // 遍历获取行
                    XSSFRow row = sheet.getRow(j);
                    try {
                        // 获取行里单元格
                        XSSFCell cell = row.getCell(0);
                        String productName = null;
                        if (cell != null) {
                            productName = cell.getStringCellValue();
                        }
                        String productTitle = row.getCell(1).getStringCellValue();
                        String productCode = row.getCell(2).getStringCellValue();
                        String productType = row.getCell(3).getStringCellValue();
                        String channel = row.getCell(4).getStringCellValue();
                        String saleType = row.getCell(5).getStringCellValue();
                        String unit = row.getCell(6).getStringCellValue();
                        Double productPrice = row.getCell(7).getNumericCellValue();

                        // 商品名不能为空
                        if (StringUtils.isBlank(productName)) {
                            throw new IllegalArgumentException("商品名不能为空");
                        }

                        // 创建数据库操作对象，将数据保存
                        ProductEntity entity = new ProductEntity();
                        entity.setProductName(productName);
                        entity.setProductTitle(productTitle);
                        entity.setProductCode(productCode);
                        entity.setUnit(unit);
                        entity.setProductPrice(productPrice);

                        // 数据转换 将给的具体值转换成符合数据库设计的值
                        if (StringUtils.isNotBlank(productType)) {
                            // TODO: 2021/10/21 此处需要去数据库查询转换
                            entity.setProductType("");
                        }
                        if (StringUtils.isNotBlank(channel)) {
                            entity.setChannel(ChannelEnum.getEnumByName(channel).getCode());
                        }
                        if (StringUtils.isNotBlank(saleType)) {
                            entity.setSaleType(SaleTypeEnum.getEnumByName(saleType).getCode());
                        }

                        // 数据必要几个字段
                        entity.preInsert();

                        // 导入的数据存在就修改，不存在就新增
                        QueryWrapper qw = new QueryWrapper();
                        /**
                         * select id from 表名
                         * select * from 表名
                         * 区别就是：查询速度
                         */
                        qw.select("id");
                        qw.eq("product_name", productName);
                        ProductEntity entity1 = productMapper.selectOne(qw);
                        if (entity1 != null) {
                            entity.setId(entity1.getId());
                            productMapper.updateById(entity);
                        } else {
                            // 插入数据
                            entity.setId(IdUtils.generateId());
                            productMapper.insert(entity);
                        }

                        successCount++;
                    } catch (Exception e) {
                        errorRows.add(row);
                        log.error("数据处理失败：" + e.getMessage(), e);
                    }
                }
            }
        }

        // 统计信息
        log.info("本次共导入" + (successCount + errorRows.size()) + "条数据，成功" + successCount + "条，失败" + errorRows.size() + "条");
        // 返回信息
        map.put("count", successCount + errorRows.size());
        map.put("successCount", successCount);
        map.put("errorCount", errorRows.size());
        return map;
    }

    /**
     * 下载导入模板
     *
     * @param fileName
     * @param response
     */
    public void download(String fileName, HttpServletResponse response) {
        UploadAndDownloadUtils.download(fileTemplate + fileName, fileName, response);
    }

    /**
     * 商品上下架
     *
     * @param ids
     * @param status
     */
    @Transactional
    public void isUp(String[] ids, Integer status) {
        String tag = "";
        // 只有O和1才进行处理
        if (status == 0) {
            status = 1;
            tag = "ON";
        } else if (status == 1) {
            status = 0;
            tag = "OFF";
        } else {
            throw new IllegalArgumentException("状态不符合设计");
        }

        // 修改状态
        for (String id : ids) {
            ProductEntity entity = new ProductEntity();
            entity.setId(id);
            entity.setIsUp(status);
            entity.preUpdate();
            productMapper.updateById(entity);
        }

        /**
         * 通知ES也要将数据进行同步
         * 不用原来的 feign 进行服务调用通知进行数据处理了
         * 使用MQ消息队列来实现
         */

        // 发送目的地  TOPIC:TAG
        String destination = "product_topic" + ":" + tag;
        // 遍历发送消息
        for (String id : ids) {
            // 发送的消息体，消息体必须存在，也就是要往MQ发送的消息
            String msg = id;

            // 业务主键作为消息key
            String key = id;

            // 构建消息
            Message message = MessageBuilder.withPayload(msg)
                    .setHeader(RocketMQHeaders.KEYS, key)
                    .build();

            // 同步发送消息
            SendResult sendResult = rocketMQTemplate.syncSend(destination, message, 60000);
            SendStatus sendStatus = sendResult.getSendStatus();
        }

    }
}